package cn.onesdream.app.api.service.Impl;

import cn.hutool.crypto.digest.MD5;
import cn.onesdream.app.api.service.UserService;
import cn.onesdream.app.common.exception.ServiceException;
import cn.onesdream.app.common.util.StringUtil;
import cn.onesdream.app.dao.entity.Role;
import cn.onesdream.app.dao.entity.User;
import cn.onesdream.app.dao.entity.UserRole;
import cn.onesdream.app.dao.mapper.UserMapper;
import cn.onesdream.app.dao.mapper.UserRoleMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * @author pc
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    public List getUserList(Integer[] userId) {
        List<User> userList = baseMapper.getByIds(userId);
        return userList;
    }

    @Override
    public User getUserByAccount(String account){
        User user = userMapper.getUserByAccount(account);
        return user;
    }

    @Override
    public List<Role> getRoleByAccount(String account){
        List<Role> roleList = userMapper.listRoleByAccount(account);
        return roleList;
    }

    @Override
    public String createToken(String account) {
        byte[] bytes = MD5.create().digest(System.currentTimeMillis() + "small_wsy_planet", "UTF-8");
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            builder.append(String.format("%02x", new Integer(b & 0xff)));
        }
        String token = builder.toString();
        User user = new User();
        user.setToken(token);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("account", account);
        userMapper.update(user, wrapper);
        return token;
    }

    @Override
    public User getUserByToken(String token){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("token", token);
        User user = userMapper.selectOne(wrapper);
        return user;
    }

    @Override
    public User getUserById(Integer userId) {
        User user = userMapper.selectById(userId);
        return user;
    }

    @Override
    public Boolean isExistByAccount(String account){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("account", account);
        Integer count = userMapper.selectCount(wrapper);
        if(count > 0){
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User insertCommonUserByPhoneNum(String phoneNum){
        User user = new User();
        user.setAccount(phoneNum);
        user.setMobile(phoneNum);
        user.setPassword(StringUtil.genRandomNum(16));
        user.setNickname("新用户" + UUID.randomUUID().toString().replace("-", "").substring(0, 8));
        Integer userInsert = userMapper.insert(user);
        Integer userId = user.getId();
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRoleMapper.insert(userRole);
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getAccount, phoneNum);
        User userInfo = baseMapper.selectOne(userQueryWrapper);
        return userInfo;
    }

    @Override
    public User loginByPassword(String account, String password) throws ServiceException {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda()
                .eq(User::getAccount, account);
        User user = baseMapper.selectOne(userQueryWrapper);
        if(user == null || !encoder.matches(password, user.getPassword())){
            throw new ServiceException("【" + account + "】登陆失败，用户名或密码错误！");
        }
        String token = createToken(account);
        user.setPassword(null);
        user.setToken(token);
        return user;
    }

    @Override
    public void changePassword(String account, String newPassword) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.lambda()
                .eq(User::getAccount, account)
                .set(User::getPassword, encoder.encode(newPassword))
                .set(User::getToken, createToken(account));
        baseMapper.update(null, userUpdateWrapper);
    }

    @Override
    public User changeUserInfo(String account, String sex, String nickname, String mobile, String birthday, String signature, String userDescribe) {
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        User user = new User();
        user.setMobile(mobile);
        user.setNickname(nickname);
        user.setSex(sex);
        user.setBirthday(birthday);
        user.setSignature(signature);
        user.setUserDescribe(userDescribe);
        userUpdateWrapper.lambda()
                .eq(User::getAccount, account);
        baseMapper.update(user, userUpdateWrapper);
        user = baseMapper.getUserByAccount(account);
        user.setPassword(null);
        return user;
    }

    @Override
    public User changeUserHead(String account, MultipartFile file) throws IOException {
        File path = new File(ResourceUtils.getURL("classpath:").getPath());
        if(!path.exists()) {
            path = new File("");
        }
        File upload = new File(path.getAbsolutePath(),"static/headImg/");
        if(!upload.exists()) {
            upload.mkdirs();
        }
        String prefix = "/headImg_";
        String httpUrl = "https://app.onesdream.cn/smallPlanet/static/headImg/";
        String originalFilename = file.getOriginalFilename();
        String fileName =  prefix + account + originalFilename.substring(originalFilename.lastIndexOf("."));
        String allFileName = upload + fileName;
        File imgFile = new File(allFileName);
        file.transferTo(imgFile.getAbsoluteFile());
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.lambda()
                .eq(User::getAccount, account)
                .set(User::getHeadImgUrl, httpUrl + fileName);
        baseMapper.update(null, userUpdateWrapper);
        User user = baseMapper.getUserByAccount(account);
        user.setPassword(null);
        return user;
    }

}



